home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / WAIS / ir / cutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-02  |  14.4 KB  |  632 lines

  1. /* Wide AREA INFORMATION SERVER SOFTWARE    
  2.    No guarantees or restrictions.  See the readme file for the full standard
  3.    disclaimer.  
  4.   
  5.    3.26.90    Harry Morris, morris@think.com
  6.    4.11.90  HWM - generalized conditional includes (see c-dialect.h)
  7.    7/19/91  speed up substrcmp by ses@ccgr.technion.ac.il (Simon E Spero)
  8. */
  9.  
  10. #define _C_C_util_
  11.  
  12. #include "cutil.h"
  13. #include "panic.h"
  14.  
  15. #include <string.h>
  16.  
  17. #ifdef ANSI_LIKE
  18. #include <stdarg.h>
  19. #else /* ndef ANSI_LIKE */
  20. #include <varargs.h>
  21. #endif /* ndef ANSI_LIKE */
  22.  
  23. #ifdef M_XENIX /* perhaps this should be in ustubs.h */
  24. #include <malloc.h>
  25. char* calloc();
  26. #endif /* def M_XENIX */
  27.  
  28. /*----------------------------------------------------------------------*/
  29.  
  30. /*#define MEMORY_ACCOUNTING*/
  31.  
  32. #ifdef MEMORY_ACCOUNTING
  33. #undef s_checkPtr
  34. #define s_checkPtr(ptr) fs_checkPtr(ptr)
  35. static FILE* memRecord = NULL;
  36. static void prepMemAcct _AP((void));
  37. static void 
  38. prepMemAcct()
  39. {
  40.   if (memRecord == NULL)
  41.     memRecord = s_fopen("MemoryAccounting","w");
  42. }
  43. static void flushMemAcct _AP((void));
  44. static void 
  45. flushMemAcct()
  46. {
  47.   fflush(memRecord);
  48. }
  49. #define tickles 0
  50. static char*     badPtr    = (char*)-1;
  51. static size_t    badSize    = -1;
  52. #endif /* def MEMORY_ACCOUNTING */
  53.  
  54. /*----------------------------------------------------------------------*/
  55.  
  56. void
  57. fs_checkPtr(ptr)
  58. void* ptr;
  59. /* If the ptr is NULL, give an error */
  60. #ifdef MEMORY_ACCOUNTING
  61. static char** ptrs = NULL;
  62. long i;
  63. static Boolean  doneSetup = false;
  64. if (doneSetup == false)
  65. {
  66. #ifdef THINK_C
  67. Debugger();
  68. #endif /* def THINK_C */
  69. doneSetup = true;
  70. }
  71. #endif /* def MEMORY_ACCOUNTING */
  72.  
  73.   if (ptr == NULL)
  74.     panic("checkPtr found a NULL pointer");
  75.  
  76. #ifdef MEMORY_ACCOUNTING
  77. /* look for specific ptr (useful when tracking un-freed memory) */
  78. if (ptr == badPtr) warn("checking found bad ptr"); 
  79. /* tickle a memory bug */
  80. if (ptrs == NULL && tickles > 0)
  81.   ptrs = (char**)malloc((size_t)tickles * sizeof(char*));
  82. for (i = 0; i < tickles; i++)
  83. { ptrs[i] = malloc((size_t)5);
  84. }
  85. for (i = 0; i < tickles; i++)
  86. { free(ptrs[i]);
  87. }
  88. #endif /* def MEMORY_ACCOUNTING */
  89.  
  90. }
  91.  
  92. /*----------------------------------------------------------------------*/
  93.  
  94. void*
  95. fs_malloc(size)
  96. size_t size;
  97. /* does safety checks and optional accounting */
  98.   register void* ptr = NULL;
  99.  
  100. #ifdef THINK_C
  101.   ptr = (void*)NewPtr((long)size);
  102.   s_checkPtr(ptr);
  103.   memset(ptr,0,(size_t)size);    /* zero it */
  104. #else  
  105.   ptr = (void*)calloc((size_t)size,(size_t)1);
  106.   s_checkPtr(ptr);
  107. #endif
  108.   
  109. #ifdef MEMORY_ACCOUNTING
  110.   /* look for specific size (useful when tracking un-freed memory) */
  111.   if (size == badSize)
  112.     warn("bad size in malloc");
  113.   
  114.   prepMemAcct();
  115.   fprintf(memRecord,"malloced %lu bytes at %lu\n",size,ptr);
  116.   flushMemAcct();
  117. #endif
  118.  
  119.   return(ptr);
  120. }
  121.  
  122. /*----------------------------------------------------------------------*/
  123.  
  124. void*
  125. fs_realloc(ptr,size)
  126. void* ptr;
  127. size_t size;
  128. /* does safety checks and optional accounting 
  129.    note - we don't know how big ptr's memory is, so we can't ensure
  130.    that any new memory allocated is NULLed!
  131.  */
  132.   register void* nptr = NULL;
  133.   
  134.   if (ptr == NULL)        /* this is really a malloc */
  135.     return(s_malloc(size));
  136.     
  137. #ifdef THINK_C
  138.   nptr = NewPtr(size);        /* need to make a copy */ 
  139.   s_checkPtr(nptr);
  140.   BlockMove(ptr,nptr,size);    /* move the old contents into it */
  141.   DisposPtr(ptr);            /* get rid of the old ones */
  142. #else
  143.   nptr = (void*)realloc(ptr,size);
  144.   s_checkPtr(ptr);
  145. #endif  
  146.    
  147. #ifdef MEMORY_ACCOUNTING
  148.   /* look for specific size (useful when tracking un-freed memory) */
  149.   if (size == badSize) 
  150.     warn("bad size in realloc");
  151.   
  152.   prepMemAcct();
  153.   fprintf(memRecord,"realloced %lu bytes at %lu from %lu\n",size,nptr,ptr);
  154.   flushMemAcct();
  155. #endif
  156.  
  157.   return(nptr);
  158. }
  159.  
  160. /*----------------------------------------------------------------------*/
  161.  
  162. void
  163. fs_free(ptr)
  164. void* ptr;
  165. /* does safety checks and optional accounting */
  166. {
  167. #ifdef MEMORY_ACCOUNTING
  168.   prepMemAcct();
  169.   /* note that the sizeof a pointer is always 4.  If only we could find out
  170.      how much space that pointer was pointing to.  Oh well, this is a place
  171.      holder for now
  172.    */
  173.   fprintf(memRecord,"freed %lu bytes at %lu\n",(size_t)sizeof(ptr),ptr);
  174.   flushMemAcct();
  175.  
  176.   /* look for specific ptr (useful when tracking un-freed memory) */
  177.   if (ptr == badPtr) warn("bad ptr in free");
  178. #endif
  179.  
  180.   if (ptr != NULL)        /* some non-ansi compilers/os's cant handle freeing null */
  181.     {                /* if we knew the size of this block of memory, we could clear it - oh well */
  182. #ifdef THINK_C
  183.       DisposPtr(ptr);
  184. #else
  185.       free(ptr);
  186. #endif
  187.     }
  188. }
  189.  
  190. /*----------------------------------------------------------------------*/
  191.  
  192. char*
  193. s_strdup(s)
  194. char* s;
  195.  
  196. /* return a copy of s.  This is identical to the standard library routine
  197.    strdup(), except that it is safe.  If s == NULL or malloc fails, 
  198.    appropriate action is taken.
  199.  */
  200. {
  201.   unsigned long len;
  202.   char* copy = NULL;
  203.   
  204.   if (s == NULL)        /* saftey check to postpone stupid errors */
  205.     return(NULL);
  206.     
  207.   len = strlen(s);        /* length of string - terminator */
  208.   copy = (char*)s_malloc((size_t)(sizeof(char)*(len + 1)));
  209.   strncpy(copy,s,len + 1);
  210.   return(copy);
  211. }
  212.  
  213. /*----------------------------------------------------------------------*/
  214.  
  215. char*
  216. fs_strncat(dst,src,maxToAdd,maxTotal)
  217. char* dst;
  218.    char* src;
  219.    size_t maxToAdd;
  220.    size_t maxTotal;
  221.  
  222. /* like strncat, except the fourth argument limits the maximum total 
  223.    length of the resulting string
  224.  */
  225. {
  226.   size_t dstSize = strlen(dst);
  227.   size_t srcSize = strlen(src);
  228.   
  229.   if (dstSize + srcSize < maxTotal) /* use regular old strncat */
  230.     return(strncat(dst,src,maxToAdd));
  231.   else
  232.     { size_t truncateTo = maxTotal - dstSize - 1;
  233.       char   saveChar = src[truncateTo];
  234.       char*  result = NULL;
  235.       src[truncateTo] = '\0';
  236.       result = strncat(dst,src,maxToAdd);
  237.       src[truncateTo] = saveChar;
  238.       return(result);
  239.     }
  240. }
  241.  
  242. /*----------------------------------------------------------------------*/
  243.  
  244. typedef long (longfunc) _AP((long c));
  245.  
  246. char*
  247. strtokf(s1,isDelimiter)
  248. char* s1;
  249. longfunc *isDelimiter; /* really *isDelimiter() */
  250.  
  251. /* This function is exactly like strtok, except that instead of passing a 
  252.    delimiter string, you pass a function that decides if a character is 
  253.    a delimiter or not, returning IS_DELIMITER or NOT_DELIMITER respecively.
  254.    Note that passing a NULL delimiter function will cause the last delimiter
  255.    to be used.
  256.  */
  257. {
  258.   static char* searchStr = NULL;
  259.   static longfunc *delimiterFunc;
  260.   long i;
  261.   char* startTok = NULL;
  262.  
  263.   if (s1 != NULL)        /* passing s1 = NULL says use the last pos */
  264.     searchStr = s1;
  265.     
  266.   if (isDelimiter != NULL)
  267.     delimiterFunc = isDelimiter;
  268.    
  269.   if (searchStr == NULL || searchStr[0] == '\0')
  270.     return(NULL);        /* nothing left to search */
  271.     
  272.   if (delimiterFunc == NULL)
  273.     return(NULL);        /* no delimiter to search with */
  274.     
  275.   /* find the start of the next token */
  276.   for (i = 0; searchStr[i] != '\0'; i++)
  277.     { if ((*delimiterFunc)((long)searchStr[i]) == NOT_DELIMITER)
  278.     break;
  279.     }
  280.   
  281.   if (searchStr[i] == '\0') 
  282.     return(NULL);        /* read to end of search string */
  283.   else
  284.     startTok = searchStr + i;    /* remember the starting point for this token*/
  285.     
  286.   /* find the end of the next token */
  287.   for (; searchStr[i] != '\0'; i++)
  288.     { if ((*delimiterFunc)((long)searchStr[i]) == IS_DELIMITER)
  289.     break;
  290.     }
  291.    
  292.   /* if the end is a delimiter (and not just the end of the search string)
  293.      replace it with '\0', and put searchStr just beyond it, otherwise
  294.      put searchStr at the terminator. */
  295.   if (searchStr[i] != '\0')
  296.     { searchStr[i] = '\0';
  297.       searchStr = searchStr + i + 1;
  298.     }
  299.   else
  300.     searchStr = searchStr + i;
  301.    
  302.   return(startTok);
  303. }
  304.  
  305. /*----------------------------------------------------------------------*/
  306.  
  307. #ifdef ANSI_LIKE /* use ansi varargs */
  308.  
  309. long
  310. cprintf(print,format)
  311. boolean print;
  312. char* format;
  313. /* just like printf, but only prints if the first argument = 1 */
  314. {
  315.   va_list ap;            /* the variable arguments */
  316.   if (print == 1)
  317.     { long res;
  318.       va_start(ap,format);    /* init ap */
  319.       res = vprintf(format,ap);    /* print the contents */
  320.       va_end(ap);        /* free ap */
  321.       return(res);
  322.     }
  323.   else
  324.     return(0);
  325. }
  326.  
  327. #else /* use k&r varargs */
  328.  
  329. long
  330. cprintf(va_alist)
  331. va_dcl
  332. /* just like printf, but only prints if the first argument = 1 */
  333. {
  334.   va_list ap;            /* the variable arguments */
  335.   boolean print;
  336.   long res;
  337.  
  338.   va_start(ap);            /* init ap */
  339.  
  340.   print = va_arg(ap,boolean);    /* get the condition */
  341.  
  342.   if (print == 1)
  343.     { char* format = va_arg(ap,char*); /* get the format */
  344. #ifdef BSD /* some folks can't do vfprintf */
  345.       res = printf("%s",format); /* just print the first thing */
  346. #else
  347.       res = vprintf(format,ap);    /* print the contents */
  348. #endif
  349.     }
  350.   else
  351.     res = 0;
  352.  
  353.   va_end(ap);            /* free ap */
  354.  
  355.   return(res);
  356. }
  357.  
  358.   
  359. #endif
  360.  
  361. extern char* log_file_name;
  362. extern FILE* logfile;
  363.  
  364. /* waislog - a new and improved logging facility.
  365.    first two arguments are important, the rest is text.
  366.  
  367.    arg1: priority.  If priority > log_level (some global), output this
  368.    message
  369.  
  370.    arg2: message code.  This is the kind of message (search, retrieval, etc).
  371. */
  372.  
  373. #ifdef ANSI_LIKE /* use ansi varargs */
  374.  
  375. void
  376. waislog(priority, message, format)
  377. long priority;
  378. long message;
  379. char *format;
  380. /* just like printf, but prints to the logfile, with PID and time. */
  381. {
  382.   va_list ap;            /* the variable arguments */
  383.   static long line = 0;
  384.  
  385.   if(logfile == NULL && log_file_name != NULL)
  386.     logfile = fopen(log_file_name, "a");
  387.  
  388.   if(logfile) {
  389.     va_start(ap, format);
  390.  
  391.     fprintf(logfile, "%d: %d: %s: %d: ", getpid(), line++, printable_time(), message);
  392.  
  393.     vfprintf(logfile, format,ap);    /* print the contents */
  394.     fprintf(logfile, "\n");
  395.     fflush(logfile);
  396.     va_end(ap);            /* free ap */
  397.   }
  398.  
  399.   if(logfile != NULL && logfile != stderr) {
  400.     fclose(logfile);
  401.     logfile = NULL;
  402.   }
  403. }
  404.  
  405. #ifdef old
  406. void
  407. waislog(priority, message, format)
  408. long priority;
  409. long message;
  410. char *format;
  411. /* just like printf, but prints to the logfile, with PID and time. */
  412. {
  413.   va_list ap;            /* the variable arguments */
  414.   static long line = 0;
  415.  
  416.   if(logfile == NULL && log_file_name != NULL)
  417.     logfile = fopen(log_file_name, "a");
  418.  
  419.   if(logfile) {
  420.     va_start(ap, priority);
  421.     message = (long)va_arg(ap, long);
  422.  
  423.     fprintf(logfile, "%d: %d: %s: %d: ", getpid(), line++, printable_time(), message);
  424.  
  425.     format = (char*)va_arg(ap, char*);
  426.  
  427.     vfprintf(logfile, format,ap);    /* print the contents */
  428.     fprintf(logfile, "\n");
  429.     fflush(logfile);
  430.     va_end(ap);            /* free ap */
  431.   }
  432.  
  433.   if(logfile != NULL && logfile != stderr) {
  434.     fclose(logfile);
  435.     logfile = NULL;
  436.   }
  437. }
  438. #endif /*old*/
  439. #else /* use k&r varargs */
  440.  
  441. #ifndef BSD
  442. void
  443. waislog(va_alist)
  444. va_dcl
  445. /* just like printf, but prints to the logfile, with PID and time. */
  446. {
  447.   va_list ap;            /* the variable arguments */
  448.   char* format;
  449.   static long line = 0;
  450.   int priority, message;
  451.  
  452.   if(logfile == NULL && log_file_name != NULL)
  453.     logfile = fopen(log_file_name, "a");
  454.  
  455.   
  456.   if(logfile) {
  457.     va_start(ap);        /* init ap */
  458.  
  459.     priority = va_arg(ap, int);
  460.     message = va_arg(ap, int);
  461.  
  462.     fprintf(logfile, "%d: %d: %s: %d: ", getpid(), line++, printable_time(), message);
  463.  
  464.     format = va_arg(ap,char*);    /* get the format */
  465.  
  466.     vfprintf(logfile, format,ap); /* print the contents */
  467.     fprintf(logfile, "\n");
  468.     fflush(logfile);
  469.     va_end(ap);            /* free ap */
  470.   }
  471.  
  472.   if(logfile != NULL && logfile != stderr) {
  473.     fclose(logfile);
  474.     logfile = NULL;
  475.   }
  476. }
  477. #endif /* NOT BSD */
  478.  
  479. #endif /* ANSI_LIKE */
  480.   
  481. /*----------------------------------------------------------------------*/
  482.  
  483. void
  484. warn(message)
  485. char* message;
  486.  
  487. {
  488. #ifdef THINK_C
  489.   Debugger();
  490. #else
  491.   printf("%s\n<press return to continue>\n",message);
  492.   getchar();
  493. #endif
  494. }
  495.  
  496. /*----------------------------------------------------------------------*/
  497. boolean substrcmp(string1,string2)
  498. char *string1, *string2;
  499. {
  500.   /* compares the strings up until one of then ends.
  501.    * returns true if they are the same, false if not.
  502.    */
  503.   register char *a, *b;
  504.   
  505.   a = string1;
  506.   b = string2;
  507.   
  508.   while (*a && *b) 
  509.     if(*a++ != *b++) 
  510.       return false;
  511.   return true;
  512. }
  513.  
  514. /*----------------------------------------------------------------------*/
  515.  
  516. char *printable_time()
  517.   static char *string;
  518.   time_t tptr;
  519.   time(&tptr);
  520.   string = ctime(&tptr);
  521.   if(string){
  522.     if(string[strlen(string)-1] == '\n')
  523.       string[strlen(string)-1] = '\0';   
  524.     return(string+4);
  525.   }
  526.   else
  527.     return("Time Unknown");
  528. }
  529.  
  530. /*----------------------------------------------------------------------*/
  531.  
  532. char char_downcase(long_ch)
  533. unsigned long long_ch;
  534. {
  535.   unsigned char ch = long_ch & 0xFF; /* just want one byte */
  536.   /* when ansi is the way of the world, this can be tolower */
  537.   return (((ch >= 'A') && (ch <= 'Z')) ? (ch + 'a' -'A') : ch);
  538. }
  539.  
  540. char *string_downcase(word)
  541. char *word;
  542. {
  543.   long i = 0;
  544.   while(word[i] != '\0'){
  545.     word[i] = char_downcase((unsigned long)word[i]);
  546.     i++;
  547.   }
  548.   return(word);
  549. }
  550.  
  551. /*----------------------------------------------------------------------*/
  552.  
  553.  
  554. /* parsing arguments functions */
  555.  
  556. char *next_arg(argc,argv)
  557. int *argc;
  558. char ***argv;
  559.  
  560.      /* Returns NULL when it is out of arguments,
  561.         This side effects both argc and argv.  argc always contains the number
  562.     of arguments left.
  563.     The first returned is the command name. 
  564.     */
  565. {
  566.   if((*argc)-- > 0)
  567.     return(*((*argv)++));
  568.   else
  569.     return(NULL);
  570. }
  571.  
  572. /*----------------------------------------------------------------------*/
  573.  
  574. char *peek_arg(argc,argv)
  575. int *argc;
  576.     char ***argv;
  577.  
  578.      /* Returns the next argument without popping it.
  579.        Returns NULL when it is out of arguments.
  580.        */
  581. {
  582.   if((*argc) > 0)
  583.     return(**argv);
  584.   else
  585.     return(NULL);
  586. }
  587.  
  588. /*----------------------------------------------------------------------*/
  589.  
  590.  
  591. #ifdef THINK_C
  592. #include <EventMgr.h>
  593. #undef MAX_FILE_NAME_LEN 
  594. #ifdef WAIStation
  595. #include "CRetrievalApp.h"
  596. #endif /* def WAIStation */
  597. #endif /* def THINK_C */
  598.  
  599. void
  600. beFriendly()
  601. /* this routine is called during time intensive operations
  602.    on single processing machines (macs and DOS).  It gives
  603.    time to other processes
  604.  */
  605. #ifdef never
  606. #ifdef THINK_C
  607.    EventRecord      macEvent;    /* an event */
  608.  
  609.    static RgnHandle    mouseRgn = NULL; /* region for mouse moved events */
  610.    long                sleepTime;     /* max time between events */
  611.    
  612. #ifdef WAIStation
  613.    gApplication->FrobWaitCursor();
  614. #endif /* def WAIStation */
  615.    
  616.    if (mouseRgn == NULL)
  617.      mouseRgn = NewRgn(); /* do we need to set its value? */
  618.      
  619.    sleepTime = 5; /* arbitrary - a tech note recommends < 50 */
  620.    
  621.    WaitNextEvent(everyEvent,&macEvent,sleepTime,mouseRgn); 
  622. #endif /* def THINK_C */
  623. #endif
  624. }
  625.  
  626. /*----------------------------------------------------------------------*/
  627.